//
// Created by baigui on 2021/11/19.
//

#include <TsDemux.h>
#include "mkv/MKVNodeBase.h"

static int getInfo(uint8_t * buffer,uint64_t *length,uint32_t *id,int *size,bool isMain = true){
    *size = 0;
    if (isMain){
        *id = AV_RB32(buffer);
        *size = *size + 4;
    } else{
        *id = AV_RB16(buffer);
        *size = *size + 2;
    }
    int lengthSize = 1;
    *length = getLength(buffer + *size, 8, &lengthSize);
    *size = *size + lengthSize;
    return 1;
}

bool MKVNodeBase::getBasicInfo() {
    auto *buf = static_cast<uint8_t *>(malloc(16));
    if (mStream->sp_stream_Peek(&buf, 16) != 16)
        return false;

    uint32_t id = 0;
    int size = 0;
    getInfo(buf,&mLength,&id,&size);
    mBasicLength = size;
    LOGV("length size: %d   %ld",size,mLength);
    delete buf;
    return true;
}

#define EBML_ID_DOCTYPE            0x4282
#define EBML_ID_EBMLVERSION        0x4286
bool HeaderNode::process() {
    uint64_t len = mLength + mBasicLength;
    uint8_t *buf = static_cast<uint8_t *>(malloc(len));
    if (mStream->sp_stream_Peek(&buf, len) != len) {
        delete buf;
        return false;
    }
    buf = buf + mBasicLength;
    uint8_t *type = nullptr;
    for (int i = 0; i < mLength;) {
        int id = AV_RB16(buf+i);
        i = i + 2;
        int size = 1;
        uint64_t length = getLength(buf + i, 8, &size);
        i = i + size;
        if(id == EBML_ID_DOCTYPE){
            type = static_cast<uint8_t *>(malloc(length));
            memcpy(type,buf + i,length);
            LOGV("file type----%s\n",type);
        } else if (id == EBML_ID_EBMLVERSION){
            LOGV("file version----%d\n",*(buf + i));
        }
        i = i + length;

    }
    int ret = false;
    if (type != nullptr) {
        ret = !memcmp("matroska", type, strlen(reinterpret_cast<const char *const>(type)));
        delete type;
    }
    delete buf;
//    LOGV("memcmp----%d",ret);
    return ret;
}

HeaderNode::HeaderNode(BaseStream *stream, uint64_t basePostion)
        : MKVNodeBase(EBML_ID_HEADER,stream,basePostion) {

}

#define MATROSKA_ID_SEGMENT    0x18538067

ContentNode::ContentNode(BaseStream *stream, uint64_t basePostion) : MKVNodeBase(MATROSKA_ID_SEGMENT, stream, basePostion) {

}

/* Matroska top-level master IDs */
#define MATROSKA_ID_INFO       0x1549A966
#define MATROSKA_ID_TRACKS     0x1654AE6B
#define MATROSKA_ID_CUES       0x1C53BB6B
#define MATROSKA_ID_TAGS       0x1254C367
#define MATROSKA_ID_SEEKHEAD   0x114D9B74
#define MATROSKA_ID_ATTACHMENTS 0x1941A469
#define MATROSKA_ID_CLUSTER    0x1F43B675
#define MATROSKA_ID_CHAPTERS   0x1043A770

bool ContentNode::process() {
    
//    mStream->sp_stream_Seek(mBasePostion + mBasicLength);
    uint8_t *buf = static_cast<uint8_t *>(malloc(16));

    for (uint64_t i = 0; i < mLength;) {
        mStream->sp_stream_Seek(i + mBasePostion + mBasicLength);
        if (mStream->sp_stream_Peek(&buf, 16) != 16) {
            delete buf;
            return false;
        }
        uint64_t length;
        uint32_t id;
        int size;
        getInfo(buf,&length,&id,&size);
        i = i + size;
        LOGV("data size : %ld data size: %d",length,size);
        switch (id){
            case MATROSKA_ID_TRACKS:
                LOGD("轨道信息");
                break;
            case MATROSKA_ID_CLUSTER:
                LOGD("文件信息");
                break;

            default:
                LOGD("not care id: %x\n",id);
                break;

        }

        i = i + length;
    }
    int ret = false;
    delete buf;
    return ret;
}
